#include "at_execute.h"

extern PubSubClient mqtt_client;
extern bool linkAllProcess;
extern bool scanNetworkFlag;
extern int linkNetworkCount;
extern bool linkMqttSerCount;
extern config_info_t configInfo;

extern void (*callback)(char *, byte *, unsigned int);

/* AT_Execute_Handler  */
bool AT_Execute_Handler(String cmd, at_cmd_parse_t *parse_cmd)
{
  if (AT_Command_Processor(cmd, parse_cmd))
  {
    if (parse_cmd->cmd_name.equals("AT")) // AT测试
    {
      AT_Ok_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("DEBUG")) // 调试指令
    {
      AT_Debug_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("WSCAN")) // 扫描热点wifi
    {
      AT_ScanNetwork_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("WCONNET")) // 连接热点wifi
    {
      AT_ConnectNetwork_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("WDISCONNET")) // 断开热点wifi
    {
      AT_DisconnectNetwork_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("WISCONNET")) // 查询热点wifi是否连接中
    {
      AT_IsconnectNetwork_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("MCONNET")) // 连接MQTT服务器
    {
      AT_ConnectMqtt_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("MDISCONNET")) // 断开MQTT服务器
    {
      AT_DisconnectMqtt_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("MACCOUNT")) // 修改MQTT登录账号
    {
      AT_AccountMqtt_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("MPUBLIC")) // 发布MQTT消息
    {
      AT_PublicMqtt_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("MSUBSCRIBE")) // 订阅MQTT消息
    {
      AT_SubscribeMqtt_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("MUNSUBSCRIBE")) // 取消订阅MQTT消息
    {
      AT_UnsubscribeMqtt_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("FSFORMAT")) // 格式化SPIFFS(清除闪存文件系统)
    {
      AT_LittleFSFormat_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("FSWRITE")) // 写入数据
    {
      AT_LittleFSWrite_Handler(parse_cmd);
    }
    else if (parse_cmd->cmd_name.equals("FSREAD")) // 读取数据
    {
      AT_LittleFSRead_Handler(parse_cmd);
    }
    else
    {
      DEBUG_LOG_print("Err+CMD:");
      DEBUG_LOG_println(parse_cmd->cmd_name); // 无效命令
    }
  }
  return true;
}

/* AT_Ok_Handler  */
bool AT_Ok_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_ACTIVE: /* rec: AT+SYSLOG */
    DEBUG_LOG_printf("OK\r\n");
    break;

  default:
    /* others are invalid command format */
    DEBUG_LOG_print("Err+OK:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_Debug_Handler  */
bool AT_Debug_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    switch ((int)parse_cmd->cmd_param.param_double[0])
    {
    case 0:
      DEBUG_LOG_print("AT_DEBUG=");
      for (int i = 0; i < parse_cmd->cmd_param.param_count; i++)
      {
        DEBUG_LOG_print(parse_cmd->cmd_param.param_double[i], 6);
        DEBUG_LOG_print(",");
      }
      DEBUG_LOG_println();
      break;

    default:
      DEBUG_LOG_printf("+DEBUG:case=%d\r\n", (int)parse_cmd->cmd_param.param_double[0]);
      break;
    }
    break;

  default:
    DEBUG_LOG_print("Err+DEBUG:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_ScanNetwork_Handler  */
bool AT_ScanNetwork_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_ACTIVE: /* rec: AT+MEM=dump,<start_address>,<length> */
    if (!WiFi.isConnected())
    {
      scanNetworkFlag = 1;
      WiFi.scanNetworks(true, true);
    }
    else
    {
      DEBUG_LOG_println("Scan can only be performed after disconnecting WiFi.");
    }
    break;
  default:
    DEBUG_LOG_print("Err+WSCAN:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_ConnectNetwork_Handler  */
bool AT_ConnectNetwork_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    configInfo.sta_ssid = parse_cmd->cmd_param.param_string[0];
    configInfo.sta_passwd = parse_cmd->cmd_param.param_string[1];
    WiFi.begin(configInfo.sta_ssid, configInfo.sta_passwd);
    linkAllProcess = 1;
    linkNetworkCount = 0;
    break;
  default:
    DEBUG_LOG_print("Err+WCONNET:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_DisconnectNetwork_Handler  */
bool AT_DisconnectNetwork_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_ACTIVE: /* rec: AT+MEM=dump,<start_address>,<length> */
    if (WiFi.isConnected())
    {
      WiFi.disconnect();
      if (!WiFi.isConnected())
      {
        DEBUG_LOG_println("WiFi disconnect done.");
      }
      else
      {
        DEBUG_LOG_println("WiFi disconnect failed.");
      }
    }
    else
    {
      DEBUG_LOG_println("WiFi is already disconnected.");
    }
    break;
  default:
    DEBUG_LOG_print("Err+WDISCONNET:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_IsconnectNetwork_Handler  */
bool AT_IsconnectNetwork_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_READ: /* rec: AT+MEM=dump,<start_address>,<length> */
    if (WiFi.isConnected())
    {
      DEBUG_LOG_println("WiFi connected.");
    }
    else
    {
      DEBUG_LOG_println("WiFi disconnected.");
    }
    break;
  default:
    DEBUG_LOG_print("Err+WISCONNET:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_ConnectMqtt_Handler  */
bool AT_ConnectMqtt_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    configInfo.mqtt_addr = parse_cmd->cmd_param.param_string[0];
    configInfo.mqtt_port = parse_cmd->cmd_param.param_double[1];
    mqtt_client.setServer(configInfo.mqtt_addr.c_str(), configInfo.mqtt_port.toInt());
    mqtt_client.setCallback(callback);
    linkAllProcess = 2;
    linkMqttSerCount = 0;
    break;
  default:
    DEBUG_LOG_print("Err+MCONENT:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_DisconnectMqtt_Handler  */
bool AT_DisconnectMqtt_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_ACTIVE: /* rec: AT+MEM=dump,<start_address>,<length> */
    mqtt_client.disconnect();
    DEBUG_LOG_println("[Waring] MQTT disconnected.");
    linkAllProcess = 0;
    break;
  default:
    DEBUG_LOG_print("Err+MDISCONENT:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_AccountMqtt_Handler  */
bool AT_AccountMqtt_Handler(at_cmd_parse_t *parse_cmd)
{
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    configInfo.mqtt_user = parse_cmd->cmd_param.param_string[0];
    configInfo.mqtt_passwd = parse_cmd->cmd_param.param_string[1];
    DEBUG_LOG_println("");
    DEBUG_LOG_println("====== MqttAccount setup ======");
    DEBUG_LOG_print("MQTT_User:");
    DEBUG_LOG_println(configInfo.mqtt_user);
    DEBUG_LOG_print("MQTT_Passwd:");
    DEBUG_LOG_println(configInfo.mqtt_passwd);
    break;
  default:
    DEBUG_LOG_print("Err+MACCOUNT:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}
/* AT_PublicMqtt_Handler  */
bool AT_PublicMqtt_Handler(at_cmd_parse_t *parse_cmd)
{
  String topic_p;
  String Payload_p;
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    topic_p = parse_cmd->cmd_param.param_string[0];
    Payload_p = parse_cmd->cmd_param.param_string[1];
    if (mqtt_client.publish(topic_p.c_str(), Payload_p.c_str()) == false)
    {
      DEBUG_LOG_println("Public mqtt send failed.");
    }
    else
    {
      DEBUG_LOG_print("MQTT-Pub[");
      DEBUG_LOG_print(topic_p);
      DEBUG_LOG_print("]:");
      DEBUG_LOG_println(Payload_p);
    }
    break;
  default:
    DEBUG_LOG_print("Err+MPUBLIC:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_SubscribeMqtt_Handler  */
bool AT_SubscribeMqtt_Handler(at_cmd_parse_t *parse_cmd)
{
  String topic_s;
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    topic_s = parse_cmd->cmd_param.param_string[0];
    if (mqtt_client.subscribe(topic_s.c_str()) == false)
    {
      DEBUG_LOG_println("Subscribe mqtt failed.");
    }
    else
    {
      DEBUG_LOG_print("Sub-topic[");
      DEBUG_LOG_print(topic_s);
      DEBUG_LOG_println("]");
    }
    break;
  default:
    DEBUG_LOG_print("Err+MSUBSCRIBE:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_UnsubscribeMqtt_Handler  */
bool AT_UnsubscribeMqtt_Handler(at_cmd_parse_t *parse_cmd)
{
  String topic_s;
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION: /* rec: AT+MEM=dump,<start_address>,<length> */
    topic_s = parse_cmd->cmd_param.param_string[0];
    if (mqtt_client.unsubscribe(topic_s.c_str()) == false)
    {
      DEBUG_LOG_println("Unsubscribe mqtt failed.");
    }
    else
    {
      DEBUG_LOG_print("Unsub-topic[");
      DEBUG_LOG_print(topic_s);
      DEBUG_LOG_println("]");
    }
    break;
  default:
    DEBUG_LOG_print("Err+MUNSUBSCRIBE:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_LittleFSFormat_Handler  */
bool AT_LittleFSFormat_Handler(at_cmd_parse_t *parse_cmd)
{
  String topic_s;
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_ACTIVE: /* rec: AT+MEM=dump,<start_address>,<length> */
    DEBUG_LOG_println("LittleFS format start");
    LittleFS.format(); // 格式化SPIFFS(清除闪存文件系统)
    DEBUG_LOG_println("LittleFS format finish");
    if (LittleFS.begin())
    {
      DEBUG_LOG_println("LittleFS Started.");
    }
    else
    {
      DEBUG_LOG_println("LittleFS Failed to Start.");
    }
    break;
  default:
    DEBUG_LOG_print("Err+FSFORMAT:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_LittleFSWrite_Handler  */
bool AT_LittleFSWrite_Handler(at_cmd_parse_t *parse_cmd)
{
  File newFile;
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_EXECUTION:                                           /* rec: AT+MEM=dump,<start_address>,<length> */
    newFile = LittleFS.open(parse_cmd->cmd_param.param_string[0], "w+"); // 建立File对象,w表示写入,r表示读取
    if (newFile)
    {
      newFile.println(parse_cmd->cmd_param.param_string[1]);
      newFile.close();
      DEBUG_LOG_println("Writing data to LittleFS");
    }
    else
    {
      Serial.println("Failed to open file for writing.");
    }
    break;
  default:
    DEBUG_LOG_print("Err+FSWRITE:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}

/* AT_LittleFSRead_Handler  */
bool AT_LittleFSRead_Handler(at_cmd_parse_t *parse_cmd)
{
  unsigned int i;
  File newFile;
  switch (parse_cmd->mode)
  {
  case AT_CMD_MODE_TESTING: /* rec: AT+MEM=dump,<start_address>,<length> */
    newFile = LittleFS.open(parse_cmd->cmd_param.param_string[0], "r");
    if (newFile) // 判断闪存文件file_name是否存在
    {
      for (i = 0; i < newFile.size(); i++)
      {
        DEBUG_LOG_print((char)newFile.read()); // File.read()读取,每次只能读取一个字符
      }
      DEBUG_LOG_println("");
      newFile.close();
    }
    else
    {
      DEBUG_LOG_println("Failed to open file for reading.");
    }
    break;
  default:
    DEBUG_LOG_print("Err+FSREAD:");
    DEBUG_LOG_println(parse_cmd->cmd_name);
    break;
  }
  return true;
}
